package com.dlc.apk.core

import android.content.Context
import android.media.MediaPlayer
import android.net.Uri
import android.text.TextUtils
import com.dlc.apk.base.BaseApp
import com.dlc.apk.utils.LogPlus


/**
 * @Author: We
 * @Date: 2020/07/09
 * @Desc:
 */
class VoiceManager private constructor() {
    private object InstanceHolder {
        val instance: VoiceManager = VoiceManager()
    }

    private var isResourceInited = false

    // 开门语音
    var doorOpen: MediaPlayer? = null
        private set

    // 关门语音
    var doorClose: MediaPlayer? = null
        private set


    //请取走电池
    var pleaseTakeOutBattery: MediaPlayer? = null
        private set

    //号仓门已打开，请放入电池
    var pleaseTakeInBattery: MediaPlayer? = null
        private set

    //请关闭仓门
    var pleaseCloseTheDoor: MediaPlayer? = null
        private set

    //请关好仓门
    var pleaseCloseTheDoorConfirm: MediaPlayer? = null
        private set

    //请输入退还码
    var pleaseInputReturnCode: MediaPlayer? = null
        private set

    //仓门打开失败
    var doorOpenFailed: MediaPlayer? = null
        private set

    //电池ID不匹配
    var batteryIdDifferent: MediaPlayer? = null
        private set

    private var isAudioPlaying: Boolean = false

    //当前正在播放的音频
    private var currentMediaPlayer: MediaPlayer? = null

    // 语音播放完成监听
    private val onCompletionListener = MediaPlayer.OnCompletionListener { mediaPlayer: MediaPlayer? -> isAudioPlaying = false }


    fun init(context: Context?) {
        isResourceInited = true
    }

    /**
     * 播放数字
     */
    fun startDigital(digital: Int? = 1, onCompletionListener: MediaPlayer.OnCompletionListener?) {
        val mp = MediaPlayer()
        val fd = BaseApp.instance.assets.openFd("${digital}号仓门已打开.mp3")
        mp.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)

        try {
            //准备好即开始播放
            mp.setOnPreparedListener { mp.start() }
            //完成之后停止播放
            mp.setOnCompletionListener {
                onCompletionListener?.onCompletion(mp)
                stopPlay(mp)
            }
            //出错之后停止播放释放资源
            mp.setOnErrorListener { mp, what, extra -> //提示用户
                onCompletionListener?.onCompletion(mp)
                stopPlay(mp)
                //释放播放器
                true
            }
            mp.setVolume(1F, 1F) //配置音量
            mp.isLooping = false //是否循环
            mp.prepareAsync()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            onCompletionListener?.onCompletion(mp)
            stopPlay(mp)
        }
    }

    /**
     * 播放 请取走电池
     */
    fun startPleaseTakeOutBattery() {
        if (pleaseTakeOutBattery != null) {
            stopPlay(pleaseTakeOutBattery)
        }
        pleaseTakeOutBattery = MediaPlayer()

        val fd = BaseApp.instance.assets.openFd("请取走电池.mp3")
        pleaseTakeOutBattery?.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)

        try {
            //准备好即开始播放
            pleaseTakeOutBattery?.setOnPreparedListener { pleaseTakeOutBattery?.start() }
            //完成之后停止播放
            pleaseTakeOutBattery?.setOnCompletionListener {
                stopPlay(pleaseTakeOutBattery)
            }
            //出错之后停止播放释放资源
            pleaseTakeOutBattery?.setOnErrorListener { mp, what, extra -> //提示用户
                stopPlay(pleaseTakeOutBattery)
                //释放播放器
                true
            }
            pleaseTakeOutBattery?.setVolume(1F, 1F) //配置音量
            pleaseTakeOutBattery?.isLooping = false //是否循环
            pleaseTakeOutBattery?.prepareAsync()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            stopPlay(pleaseTakeOutBattery)
        }
    }

    /**
     * 播放 请放入电池
     */
    fun startPleaseTakeInBattery() {
        if (pleaseTakeInBattery != null) {
            stopPlay(pleaseTakeInBattery)
        }
        pleaseTakeInBattery = MediaPlayer()

        val fd = BaseApp.instance.assets.openFd("请放入电池.mp3")
        pleaseTakeInBattery?.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)

        try {
            //准备好即开始播放
            pleaseTakeInBattery?.setOnPreparedListener { pleaseTakeInBattery?.start() }
            //完成之后停止播放
            pleaseTakeInBattery?.setOnCompletionListener { stopPlay(pleaseTakeInBattery) }
            //出错之后停止播放释放资源
            pleaseTakeInBattery?.setOnErrorListener { mp, what, extra -> //提示用户
                stopPlay(pleaseTakeInBattery)
                //释放播放器
                true
            }
            pleaseTakeInBattery?.setVolume(1F, 1F) //配置音量
            pleaseTakeInBattery?.isLooping = false //是否循环
            pleaseTakeInBattery?.prepareAsync()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            stopPlay(pleaseTakeInBattery)
        }
    }

    /**
     * 播放 请关闭仓门
     */
    fun startPleaseCloseTheDoor() {
        if (pleaseCloseTheDoor != null) {
            stopPlay(pleaseCloseTheDoor)
        }
        pleaseCloseTheDoor = MediaPlayer()

        val fd = BaseApp.instance.assets.openFd("please_close_door.mp3")
        pleaseCloseTheDoor?.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)

        try {
            //准备好即开始播放
            pleaseCloseTheDoor?.setOnPreparedListener { pleaseCloseTheDoor?.start() }
            //完成之后停止播放
            pleaseCloseTheDoor?.setOnCompletionListener { stopPlay(pleaseCloseTheDoor) }
            //出错之后停止播放释放资源
            pleaseCloseTheDoor?.setOnErrorListener { mp, what, extra -> //提示用户
                stopPlay(pleaseCloseTheDoor)
                //释放播放器
                true
            }
            pleaseCloseTheDoor?.setVolume(1F, 1F) //配置音量
            pleaseCloseTheDoor?.isLooping = false //是否循环
            pleaseCloseTheDoor?.prepareAsync()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            stopPlay(pleaseCloseTheDoor)
        }
    }

    /**
     * 播放 请关好仓门
     */
    fun startPleaseCloseTheDoorConfirm() {
        if (pleaseCloseTheDoorConfirm != null) {
            stopPlay(pleaseCloseTheDoorConfirm)
        }
        pleaseCloseTheDoorConfirm = MediaPlayer()

        val fd = BaseApp.instance.assets.openFd("please_close_door_confirm.mp3")
        pleaseCloseTheDoorConfirm?.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)

        try {
            //准备好即开始播放
            pleaseCloseTheDoorConfirm?.setOnPreparedListener { pleaseCloseTheDoorConfirm?.start() }
            //完成之后停止播放
            pleaseCloseTheDoorConfirm?.setOnCompletionListener { stopPlay(pleaseCloseTheDoorConfirm) }
            //出错之后停止播放释放资源
            pleaseCloseTheDoorConfirm?.setOnErrorListener { mp, what, extra -> //提示用户
                stopPlay(pleaseCloseTheDoorConfirm)
                //释放播放器
                true
            }
            pleaseCloseTheDoorConfirm?.setVolume(1F, 1F) //配置音量
            pleaseCloseTheDoorConfirm?.isLooping = false //是否循环
            pleaseCloseTheDoorConfirm?.prepareAsync()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            stopPlay(pleaseCloseTheDoorConfirm)
        }
    }

    /**
     * 播放 请输入归还码
     */
    fun startPleaseInputReturnCode() {
        if (pleaseInputReturnCode != null) {
            stopPlay(pleaseInputReturnCode)
        }
        pleaseInputReturnCode = MediaPlayer()

        val fd = BaseApp.instance.assets.openFd("please_input_code.mp3")
        pleaseInputReturnCode?.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)

        try {
            //准备好即开始播放
            pleaseInputReturnCode?.setOnPreparedListener { pleaseInputReturnCode?.start() }
            //完成之后停止播放
            pleaseInputReturnCode?.setOnCompletionListener { stopPlay(pleaseInputReturnCode) }
            //出错之后停止播放释放资源
            pleaseInputReturnCode?.setOnErrorListener { mp, what, extra -> //提示用户
                stopPlay(pleaseInputReturnCode)
                //释放播放器
                true
            }
            pleaseInputReturnCode?.setVolume(1F, 1F) //配置音量
            pleaseInputReturnCode?.isLooping = false //是否循环
            pleaseInputReturnCode?.prepareAsync()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            stopPlay(pleaseInputReturnCode)
        }
    }

    /**
     * 播放 仓门打开失败
     */
    fun startDoorOpenFailed() {
        if (doorOpenFailed != null) {
            stopPlay(doorOpenFailed)
        }
        doorOpenFailed = MediaPlayer()

        val fd = BaseApp.instance.assets.openFd("door_open_failed.mp3")
        doorOpenFailed?.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)

        try {
            //准备好即开始播放
            doorOpenFailed?.setOnPreparedListener { doorOpenFailed?.start() }
            //完成之后停止播放
            doorOpenFailed?.setOnCompletionListener { stopPlay(doorOpenFailed) }
            //出错之后停止播放释放资源
            doorOpenFailed?.setOnErrorListener { mp, what, extra -> //提示用户
                stopPlay(doorOpenFailed)
                //释放播放器
                true
            }
            doorOpenFailed?.setVolume(1F, 1F) //配置音量
            doorOpenFailed?.isLooping = false //是否循环
            doorOpenFailed?.prepareAsync()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            stopPlay(doorOpenFailed)
        }
    }


    fun startDoorOpen() {
        if (doorOpen != null) {
            stopPlay(doorOpen)
        }
        doorOpen = MediaPlayer()
        /*开门欢迎语*/
        if (!TextUtils.isEmpty(doorOpenVoiceFileUrl)) {
            doorOpen?.setDataSource(BaseApp.instance, Uri.parse(doorOpenVoiceFileUrl))
        } else {
            val fd = BaseApp.instance.assets.openFd("d1.mp3")
            doorOpen?.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)
        }

        try {
            //准备好即开始播放
            doorOpen?.setOnPreparedListener { doorOpen?.start() }
            //完成之后停止播放
            doorOpen?.setOnCompletionListener { stopPlay(doorOpen) }
            //出错之后停止播放释放资源
            doorOpen?.setOnErrorListener { mp, what, extra -> //提示用户
                stopPlay(doorOpen)
                //释放播放器
                true
            }
            doorOpen?.setVolume(1F, 1F) //配置音量
            doorOpen?.isLooping = false //是否循环
            doorOpen?.prepareAsync()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            stopPlay(doorOpen)
        }
    }

    fun startDoorClose() {
        if (doorClose != null) {
            stopPlay(doorClose)
        }
        /*开门欢迎语*/

        if (!TextUtils.isEmpty(closeVoiceFileUrl)) {
            doorClose = MediaPlayer()
            doorClose?.setDataSource(BaseApp.instance, Uri.parse(closeVoiceFileUrl))
        }

        try {
            //准备好即开始播放
            doorClose?.setOnPreparedListener { doorClose?.start() }
            //完成之后停止播放
            doorClose?.setOnCompletionListener { stopPlay(doorClose) }
            //出错之后停止播放释放资源
            doorClose?.setOnErrorListener { mp, what, extra -> //提示用户
                stopPlay(doorClose)
                //释放播放器
                true
            }
            doorClose?.setVolume(1F, 1F) //配置音量
            doorClose?.isLooping = false //是否循环
            doorClose?.prepareAsync()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            stopPlay(doorClose)
        }
    }

    /**
     * 播放 电池不匹配
     */
    fun startBatteryIdDifferent() {
        if (batteryIdDifferent != null) {
            stopPlay(batteryIdDifferent)
        }
        batteryIdDifferent = MediaPlayer()

        val fd = BaseApp.instance.assets.openFd("电池不匹配.mp3")
        batteryIdDifferent?.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)

        try {
            //准备好即开始播放
            batteryIdDifferent?.setOnPreparedListener { batteryIdDifferent?.start() }
            //完成之后停止播放
            batteryIdDifferent?.setOnCompletionListener { stopPlay(batteryIdDifferent) }
            //出错之后停止播放释放资源
            batteryIdDifferent?.setOnErrorListener { mp, what, extra -> //提示用户
                stopPlay(batteryIdDifferent)
                //释放播放器
                true
            }
            batteryIdDifferent?.setVolume(1F, 1F) //配置音量
            batteryIdDifferent?.isLooping = false //是否循环
            batteryIdDifferent?.prepareAsync()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            stopPlay(batteryIdDifferent)
        }
    }

    /**
     * @param mp
     */
    private fun start(mp: MediaPlayer?) {
        if (mp == null) {
            LogPlus.e("###mp is null")
            return
        }
        if (!isResourceInited) {
            throw RuntimeException("请先调用初始化")
        }
        try {
            if (currentMediaPlayer != null && currentMediaPlayer!!.isPlaying) {
                currentMediaPlayer?.pause()
            }
            currentMediaPlayer = mp

            mp.setOnCompletionListener(onCompletionListener)

            mp.setOnErrorListener(MediaPlayer.OnErrorListener { p0, p1, p2 ->
                LogPlus.e("###error -> $p0,$p1,$p2")
                true
            })
        } catch (e: Exception) {
            e.printStackTrace()
        }
        isAudioPlaying = true
        try {
            // Mediaplayer连续播放没有声音的问题
            //这个问题太头疼了，有些手机甚至会卡死，原因是内存泄漏引起的。
            //解决办法：定义一个MediaPlayer变量，每次播放时释放上一次播放的资源
            mp.seekTo(0)
            mp.start()
        } catch (e: Exception) {
            LogPlus.e("###无法播放, 异常message->${e.message},${LogPlus.getStackTraceInfo(e)}")
            mp.setOnPreparedListener {
                mp.start()
            }
            mp.reset()
            mp.prepareAsync()
        }
    }

    companion object {
        fun getInstance(): VoiceManager {
            return InstanceHolder.instance
        }
    }

    private var doorOpenVoiceFileUrl: String? = null
    fun updateDoorOpen(url: String?) {
        if (TextUtils.isEmpty(url)) {
            return
        }
        this.doorOpenVoiceFileUrl = url
        doorOpen = MediaPlayer()
        doorOpen?.setOnPreparedListener {

        }
        try {
            doorOpen?.setDataSource(BaseApp.instance, Uri.parse(url))
            doorOpen?.prepareAsync()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private var closeVoiceFileUrl: String? = null
    fun updateDoorClose(url: String?) {
        if (TextUtils.isEmpty(url)) {
            return
        }
        closeVoiceFileUrl = url
        doorClose = MediaPlayer()
        doorClose?.setOnPreparedListener {

        }
        try {
            doorClose?.setDataSource(BaseApp.instance, Uri.parse(url))
            doorClose?.prepareAsync()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun release() {
        doorOpen?.stop()
        doorOpen?.release()
        doorClose?.stop()
        doorClose?.release()
    }

    fun stopPlay(mMediaPlayer: MediaPlayer?) {
        if (mMediaPlayer != null) {
            try {
                if (mMediaPlayer.isPlaying) {
                    mMediaPlayer.stop()
                }
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }

            try {
                mMediaPlayer.release()
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
        }
    }
}